package com.android.systemui.ios.views;

import android.app.WallpaperManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import com.android.systemui.ios.Constants;
import com.android.systemui.ios.IActionEventCallback;
import com.android.systemui.ios.IGuardService;
import com.android.systemui.ios.IStatusBarCallback;
import com.android.systemui.ios.R;
import com.android.systemui.ios.ScreenBlurTask;

import java.util.Locale;

public class PageDateTimeView extends FrameLayout implements IStatusBarCallback {

    private final boolean DEBUG = false;
    private final String TAG = "wss";

    private final float CAMERA_SCALE_MIN = 0.9f;
    private final float TIME_SCALE_MIN = 0.95f;

    private final int STATE_RESET = 0;
    private final int STATE_WIDGET = 1;
    private final int STATE_CAMERA = 2;

    private ImageView mImageBackground;
    private ImageView mImageOverlay;
    private View mChildCamera;
    private View mChildTime;
    private View mChildWidget;
    private View mSystemIcons;
    private View mShortcutBlurView;
    private ImageView mShortcutIconTorch;
    private ImageView mShortcutIconCamera;
    private PasswordInputView mPasswordLayout;
    private ImageView mKeyguardLockIcon;
    private FrameLayout mFaceContainer;

    private TextView mBarTextCarrierName;
    private ImageView mBarIconSim1Signal;
    private ImageView mBarIconSim2Signal;
    private ImageView mBarIcon4GWifi;
    private TextView mBarTextBatPercent;

    private Vibrator mVibrator;
    private VelocityTracker mVelocityTracker;
    private IGuardService mService;
    private IActionEventCallback mEventCallback;

    private int mState = STATE_RESET;
    private int mDeltaX;
    private int mDeltaY;
    private int mWidgetLayoutWidth;
    private float mWidgetPagerTouchSlopRatio = 1.0f;
    private float mLastMotionX;
    private float mLastMotionY;
    private boolean isFaceOk = false;
    private boolean isInIgnoredArea = false;
    private boolean isLongCancelled = true;
    private boolean mIsTorchOpen = false;

    public PageDateTimeView(Context context) {
        this(context, null, 0);
    }

    public PageDateTimeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PageDateTimeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mVibrator = getContext().getSystemService(Vibrator.class);
        mWidgetLayoutWidth = getResources().getDimensionPixelSize(R.dimen.widget_pager_layout_width);
        mWidgetPagerTouchSlopRatio = mWidgetLayoutWidth * 1.0f / Constants.screenWidth;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mImageBackground = findViewById(R.id.image_background);
        mImageOverlay = findViewById(R.id.image_overlay);
        mChildCamera = findViewById(R.id.pg_camera);
        mChildTime = findViewById(R.id.pg_time);
        mChildWidget = findViewById(R.id.pg_widget);
        mSystemIcons = findViewById(R.id.layout_system_icons);
        mPasswordLayout = findViewById(R.id.page_password_layout);
        mKeyguardLockIcon = findViewById(R.id.pg_keyguard_lock_icon);
        mFaceContainer = findViewById(R.id.face_preview_container);

        mBarTextCarrierName = findViewById(R.id.bar_tv_carrier_name);
        mBarIconSim1Signal = findViewById(R.id.bar_iv_sim1_signal);
        mBarIconSim2Signal = findViewById(R.id.bar_iv_sim2_signal);
        mBarIcon4GWifi = findViewById(R.id.bar_iv_4g_wifi);
        mBarTextBatPercent = findViewById(R.id.bar_battery_percent);

        mChildCamera.setScaleX(CAMERA_SCALE_MIN);
        mChildCamera.setScaleY(CAMERA_SCALE_MIN);
        mChildCamera.setAlpha(0.0f);
        mChildWidget.setX(-mWidgetLayoutWidth);
        mChildWidget.setVisibility(VISIBLE);

        mPasswordLayout.setOnInputChangedListener(new PasswordInputView.OnInputChangedListener() {

            @Override
            public void onCancel() {
                setPasswordVisible(false);
            }

            @Override
            public void onVerify(String str) {
                if (mService != null) {
                    if (mService.requestVerify(str) == 1) {
                        setPasswordVisible(false);
                        if (mEventCallback != null) {
                            mEventCallback.onAnimationCollapse();
                        }
                    } else {
                        mPasswordLayout.verifyError();
                    }
                }
            }

            @Override
            public void onEmergencyCall() {
                if (mService != null) {
                    mService.openEmergencyCall();
                }
            }
        });

        mShortcutIconTorch = (ImageView) findViewById(R.id.image_shortcut_torch);
        if (mShortcutIconTorch != null) {
            mShortcutIconTorch.setOnLongClickListener(mShortcutLongClickListener);
            mShortcutIconTorch.setOnTouchListener(mShortcutTouchListener);
            refreshFlashLight();
        }

        mShortcutIconCamera = (ImageView) findViewById(R.id.image_shortcut_camera);
        if (mShortcutIconCamera != null) {
            mShortcutIconCamera.setOnLongClickListener(mShortcutLongClickListener);
            mShortcutIconCamera.setOnTouchListener(mShortcutTouchListener);
        }
    }

    public void setPageShortcutView(PageShortcutView view) {
        mShortcutBlurView = view;
    }

    public boolean isFaceDiscernSuccess() {
        return isFaceOk;
    }

    public void setLockIconLocked(boolean lock) {
        if (mKeyguardLockIcon != null) {
            mKeyguardLockIcon.setImageResource(lock ? R.drawable.ip_keyguard_icon_lock : R.drawable.ip_keyguard_icon_unlock);
        }
    }

    public void setShowLockIcon(boolean show) {
        isFaceOk = false;
        if (mKeyguardLockIcon != null) {
            mKeyguardLockIcon.setVisibility(show ? VISIBLE : INVISIBLE);
        }
    }

    public void setFacePreviewEnable(boolean en) {
        mFaceContainer.removeAllViews();
    }

    public void updateLocation(boolean force) {
        if (mChildWidget.getX() < 0 || force) {
            mChildWidget.setX(-mWidgetLayoutWidth);
        }
    }

    private final View.OnLongClickListener mShortcutLongClickListener = new View.OnLongClickListener() {

        @Override
        public boolean onLongClick(View v) {
            final int id = v.getId();
            if (R.id.image_shortcut_torch == id) {
                if (mVibrator != null) {
                    mVibrator.vibrate(50);
                }
                if (mService != null) {
                    mIsTorchOpen = !mIsTorchOpen;
                    mService.setTorchEnabled(mIsTorchOpen);
                }
            } else if (R.id.image_shortcut_camera == id) {
                if (mVibrator != null) {
                    mVibrator.vibrate(50);
                }
                if (mEventCallback != null) {
                    mEventCallback.onOpenCamera();
                    mEventCallback.onAnimationCollapse();
                }
            }
            return false;
        }
    };

    private final View.OnTouchListener mShortcutTouchListener = new View.OnTouchListener() {

        private boolean isCancelled = false;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    isCancelled = false;
                    v.animate().setStartDelay(100).scaleX(1.3f).scaleY(1.3f).setDuration(300).start();
                    break;
                case MotionEvent.ACTION_MOVE:
                    break;
                default:
                    if (!isCancelled) {
                        isCancelled = true;
                        v.animate().scaleX(1.0f).scaleY(1.0f).setDuration(150).start();
                    }
                    break;
            }
            return false;
        }
    };

    private final BroadcastReceiver mTorchChangedReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if ("android.sec.action.TORCH_CHANGED".equals(intent.getAction())) {
                refreshFlashLight();
            } else if (Intent.ACTION_WALLPAPER_CHANGED.equals(action)) {
                updateWallpaper();
            }
        }
    };

    private void updateWallpaper() {
        WallpaperManager wm = getContext().getSystemService(WallpaperManager.class);
        Bitmap bitmap = null;//wm.getDefaultLockWallpaper();
        if (bitmap == null) {
            Drawable drawable = wm.getBuiltInDrawable();
            if (drawable instanceof BitmapDrawable) {
                bitmap = ((BitmapDrawable) drawable).getBitmap();
            }
        }
        if (bitmap != null) {
            mImageBackground.setImageBitmap(bitmap);
            final int width = bitmap.getWidth();
            final int height = bitmap.getHeight();
            int scaleW = width * height / Constants.screenHeight;
            ScreenBlurTask.from(getContext(), bitmap)
                    .setClipRegion((width - scaleW) / 2, 0, scaleW, height)
                    .generate(new ScreenBlurTask.Callback() {

                        @Override
                        public void onResult(Bitmap result) {
                            if (mShortcutBlurView != null) {
                                mShortcutBlurView.setBackground(new BitmapDrawable(getResources(), result));
                            }
                        }
                    });
            ScreenBlurTask.from(getContext(), bitmap)
                    .setOverlayColor(0x80000000)
                    .setClipRegion((width - scaleW) / 2, 0, scaleW, height)
                    .generate(new ScreenBlurTask.Callback() {

                        @Override
                        public void onResult(Bitmap result) {
                            mImageOverlay.setImageBitmap(result);
                        }
                    });
        }
    }

    private void refreshFlashLight() {
        if (mShortcutIconTorch == null) {
            return;
        }
        if (mService != null && mService.isTorchEnabled()) {
            mIsTorchOpen = true;
            mShortcutIconTorch.setImageResource(R.drawable.iphone_shortcut_image_torch_open);
        } else {
            mIsTorchOpen = false;
            mShortcutIconTorch.setImageResource(R.drawable.iphone_shortcut_image_torch_close);
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.sec.action.TORCH_CHANGED");
        filter.addAction(Intent.ACTION_WALLPAPER_CHANGED);
        getContext().registerReceiver(mTorchChangedReceiver, filter);
        updateWallpaper();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        getContext().unregisterReceiver(mTorchChangedReceiver);
    }

    public void updatePasswordLayout(int deltaY) {
        float y = Constants.screenHeight * 0.6f - deltaY;
        float alpha = Math.min(Math.abs(deltaY) / (Constants.screenHeight * 0.5f), 1.0f);
        float scale = Math.min(Math.abs(1.0f - alpha * (1 - TIME_SCALE_MIN)), 1.0f);
        mChildTime.setScaleX(scale);
        mChildTime.setScaleY(scale);
        mPasswordLayout.setAlpha(alpha);
        mPasswordLayout.setVisibility(VISIBLE);
        mPasswordLayout.setY(Math.max(y, 0));
        mImageOverlay.setAlpha(alpha);
    }

    public void setPasswordVisible(boolean show) {
        if (show) {
            mPasswordLayout.setVisibility(VISIBLE);
            mChildTime.animate().scaleX(TIME_SCALE_MIN).scaleY(TIME_SCALE_MIN).start();
            mImageOverlay.animate().alpha(1.0f).start();
            mPasswordLayout.animate().translationY(0).alpha(1.0f).start();
        } else {
            mChildTime.animate().scaleX(1.0f).scaleY(1.0f).start();
            mImageOverlay.animate().alpha(0.0f).start();
            mPasswordLayout.animate().translationY(Constants.screenHeight).alpha(0.0f).withEndAction(new Runnable() {

                @Override
                public void run() {
                    mPasswordLayout.resetAll();
                    mPasswordLayout.setVisibility(GONE);
                }
            }).start();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final int action = event.getAction();
        final float x = event.getX();
        final float y = event.getY();
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mLastMotionX = x;
                mLastMotionY = y;
                isInIgnoredArea = (y > (Constants.screenHeight - Constants.unlockBottomHeight)) || (y < Constants.slideTopBarHeight);
                if (!isInIgnoredArea) {
                    if (mState == STATE_RESET) {
                        isLongCancelled = false;
                        removeCallbacks(mSimLongClickRunnable);
                        postDelayed(mSimLongClickRunnable, 600);
                    }
                }
                break;

            case MotionEvent.ACTION_MOVE:
                mDeltaX = (int) (mLastMotionX - x);
                mDeltaY = (int) (mLastMotionY - y);
                float alpha = Math.min((Math.abs(mDeltaX) * 1.0f) / Constants.pageTurningSize, 1.0f);
                if (DEBUG)
                    Log.i(TAG, "date time move : x=" + mDeltaX + ", y=" + mDeltaY + ", alpha=" + alpha + ", isInIgnoredArea=" + isInIgnoredArea);
                if (mState == STATE_WIDGET) {
                    if (mDeltaX > 0) {
                        mChildWidget.setX(-mDeltaX);
                        mImageOverlay.setAlpha(1 - alpha);
                    } else {
                        mChildWidget.setX(0);
                        mImageOverlay.setAlpha(1.0f);
                    }
                } else if (mState == STATE_RESET) {
                    if (mDeltaX <= 0) {
                        int offset = -mWidgetLayoutWidth - mDeltaX;
                        mChildWidget.setX(Math.min(offset, 0));
                        float scale = Math.min(Math.abs(1.0f - alpha * (1 - TIME_SCALE_MIN)), 1.0f);
                        mChildTime.setScaleX(scale);
                        mChildTime.setScaleY(scale);
                        mImageOverlay.setAlpha(alpha);
                    } else {
                        float scale = Math.min(CAMERA_SCALE_MIN + alpha * (1.0f - CAMERA_SCALE_MIN), 1.0f);
                        mChildWidget.setX(-mWidgetLayoutWidth);
                        mImageBackground.setX(-mDeltaX);
                        mSystemIcons.setX(-mDeltaX);
                        mChildTime.setX(-mDeltaX);
                        mChildTime.setScaleX(1.0f);
                        mChildTime.setScaleY(1.0f);
                        mChildCamera.setScaleX(scale);
                        mChildCamera.setScaleY(scale);
                        mChildCamera.setAlpha(alpha);
                    }
                    if (!isLongCancelled) {
                        if (Math.abs(mDeltaX) > 2 || Math.abs(mDeltaY) > 2) {
                            isLongCancelled = true;
                            removeCallbacks(mSimLongClickRunnable);
                        }
                    }
                }
                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mVelocityTracker.computeCurrentVelocity(500);
                float velocityX = mVelocityTracker.getXVelocity();
                if (!isLongCancelled) {
                    isLongCancelled = true;
                    removeCallbacks(mSimLongClickRunnable);
                }
                if (DEBUG)
                    Log.i(TAG, "date time up : mState=" + mState + ", velocityX=" + velocityX + ", mDeltaX=" + mDeltaX);
                if (mState == STATE_RESET) {
                    if (velocityX > Constants.pageTurningVelocity || mDeltaX < -(Constants.pageTurningSize * mWidgetPagerTouchSlopRatio)) {
                        mState = STATE_WIDGET;
                        mChildWidget.animate().translationX(0).start();
                        mChildTime.animate().translationX(0).scaleX(TIME_SCALE_MIN).scaleY(TIME_SCALE_MIN).start();
                        mChildCamera.animate().alpha(0.0f).scaleX(CAMERA_SCALE_MIN).scaleY(CAMERA_SCALE_MIN).start();
                        mImageOverlay.animate().alpha(1.0f).start();
                        mImageBackground.animate().translationX(0).start();
                        mSystemIcons.animate().translationX(0).start();
                    } else if (velocityX < -Constants.pageTurningVelocity || mDeltaX > Constants.pageTurningSize) {
                        mState = STATE_CAMERA;
                        mChildTime.animate().translationX(-Constants.screenWidth).scaleX(1.0f).scaleY(1.0f).start();
                        mChildWidget.animate().translationX(-Constants.screenWidth).start();
                        mImageOverlay.animate().alpha(0.0f).start();
                        mImageBackground.animate().translationX(-Constants.screenWidth).start();
                        mSystemIcons.animate().translationX(-Constants.screenWidth).start();
                        mChildCamera.animate().scaleX(1.0f).scaleY(1.0f).alpha(1.0f).withEndAction(new Runnable() {

                            @Override
                            public void run() {
                                mState = STATE_RESET;
                                mChildWidget.animate().translationX(-mWidgetLayoutWidth).start();
                                mChildTime.animate().translationX(0).scaleX(1.0f).scaleY(1.0f).start();
                                mChildCamera.animate().alpha(0.0f).scaleX(CAMERA_SCALE_MIN).scaleY(CAMERA_SCALE_MIN).start();
                                mImageOverlay.animate().alpha(0.0f).start();
                                mImageBackground.animate().translationX(0).start();
                                mSystemIcons.animate().translationX(0).start();
                                if (mEventCallback != null) {
                                    mEventCallback.onCollapse();
                                }
                            }
                        }).start();
                        if (mEventCallback != null) {
                            mEventCallback.onOpenCamera();
                        }
                    } else {
                        mChildWidget.animate().translationX(-mWidgetLayoutWidth).start();
                        mChildTime.animate().translationX(0).scaleX(1.0f).scaleY(1.0f).start();
                        mChildCamera.animate().alpha(0.0f).scaleX(CAMERA_SCALE_MIN).scaleY(CAMERA_SCALE_MIN).start();
                        mImageOverlay.animate().alpha(0.0f).start();
                        mImageBackground.animate().translationX(0).start();
                        mSystemIcons.animate().translationX(0).start();
                    }
                } else if (mState == STATE_WIDGET) {
                    if (velocityX < -Constants.pageTurningVelocity || mDeltaX > (Constants.pageTurningSize * mWidgetPagerTouchSlopRatio)) {
                        mState = STATE_RESET;
                        mChildWidget.animate().translationX(-mWidgetLayoutWidth).start();
                        mChildTime.animate().translationX(0).scaleX(1.0f).scaleY(1.0f).start();
                        mImageOverlay.animate().alpha(0.0f).start();
                    } else {
                        mImageOverlay.animate().alpha(1.0f).start();
                        mChildWidget.animate().translationX(0).start();
                    }
                }
                break;
        }

        if (isInIgnoredArea) {
            return super.onTouchEvent(event);
        }

        return true;
    }

    public void resetCenter() {
        isFaceOk = false;
        mState = STATE_RESET;
        mChildWidget.animate().translationX(-mWidgetLayoutWidth).start();
        mChildTime.animate().translationX(0).scaleX(1.0f).scaleY(1.0f).start();
        mChildCamera.animate().alpha(0.0f).scaleX(CAMERA_SCALE_MIN).scaleY(CAMERA_SCALE_MIN).start();
        mImageOverlay.animate().alpha(0.0f).start();
        mImageBackground.animate().translationX(0).start();
        mSystemIcons.animate().translationX(0).start();
        setPasswordVisible(false);
    }

    private final Runnable mSimLongClickRunnable = new Runnable() {

        @Override
        public void run() {
            if (!isLongCancelled && mEventCallback != null) {
                mEventCallback.onEntryWallpaperManager();
            }
            isLongCancelled = true;
        }
    };

    public void setActionEventCallback(IGuardService service, IActionEventCallback callback) {
        mService = service;
        mEventCallback = callback;
    }

    @Override
    public void onDisturbChanged(boolean open) {

    }

    @Override
    public void onBrightnessChanged(boolean auto, int brightness) {

    }

    @Override
    public void onAirplaneModeChanged(boolean open) {

    }

    @Override
    public void onHotspotStateChanged(boolean enabled, int numDevices) {

    }

    @Override
    public void onGpsChanged(boolean open, boolean active) {

    }

    @Override
    public void onBluetoothChanged(boolean open, boolean connected, String name) {

    }

    @Override
    public void onWifiChanged(boolean open, boolean connected, int signal, int network, String name) {
        if (connected) {
            mBarIcon4GWifi.setVisibility(VISIBLE);
            switch (signal) {
                case 0:
                    mBarIcon4GWifi.setImageResource(R.drawable.ip_ic_qs_wifi_0);
                    break;
                case 1:
                    mBarIcon4GWifi.setImageResource(R.drawable.ip_ic_qs_wifi_1);
                    break;
                case 2:
                    mBarIcon4GWifi.setImageResource(R.drawable.ip_ic_qs_wifi_2);
                    break;
                case 3:
                    mBarIcon4GWifi.setImageResource(R.drawable.ip_ic_qs_wifi_3);
                    break;
                case 4:
                default:
                    mBarIcon4GWifi.setImageResource(R.drawable.ip_ic_qs_wifi_4);
                    break;
            }
        } else {
            mBarIcon4GWifi.setVisibility(GONE);
        }
    }

    @Override
    public void onSimStateChanged(int count, int subId, boolean insert, int signal, int network, int dataType, String name) {
        if (count == 0) {
            mBarIconSim1Signal.setImageResource(0);
            mBarIconSim2Signal.setImageResource(0);
            mBarTextCarrierName.setText("");
        } else if (count == 1) {
            if (signal == 11) { // 11:airplane  12:searching
                mBarIconSim1Signal.setImageResource(R.drawable.ip_ic_qs_airplane);
                mBarIconSim2Signal.setImageResource(0);
                mBarTextCarrierName.setText("");
            } else {
                mBarIconSim1Signal.setImageResource(Constants.SingleSimStrengthIds[Math.max(Math.min(signal, 4), 0)]);
                mBarIconSim2Signal.setImageResource(0);
                mBarTextCarrierName.setText(name);
            }
        } else {
            if (subId == 1) {
                mBarIconSim1Signal.setImageResource(Constants.DualSim1StrengthIds[Math.max(Math.min(signal, 4), 0)]);
                mBarTextCarrierName.setText(name);
            } else if (subId == 2) {
                mBarIconSim2Signal.setImageResource(Constants.DualSim2StrengthIds[Math.max(Math.min(signal, 4), 0)]);
//                mBarTextCarrierName.setText(name);
            }
        }
    }

    @Override
    public void onTorchChanged(boolean available, boolean open) {
        refreshFlashLight();
    }

    @Override
    public void onAudioStateChanged(int stream, int volume, boolean silent, boolean vibrate) {

    }

    @Override
    public void onScreenAutoRotationChanged(boolean open) {

    }

    @Override
    public void onScreenRecordingChanged(int state, int time) {

    }

    @Override
    public void onBatteryChanged(int level, boolean pluggedIn, boolean charging, boolean powerSave) {
        if (mBarTextBatPercent != null) {
            mBarTextBatPercent.setText(String.format(Locale.US, "%d%%", level));
        }
    }
}
